﻿using Flurl.Http;
using NovelDownload.Common;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace NovelDownload
{
    /// <summary>
    /// 炫书网
    /// </summary>
    public class XswNovelSite : NovelSiteBase, INovelSiteBase
    {
        public XswNovelSite()
            : base() { }


        public XswNovelSite(string siteName, string siteHomeUrl, string searchSubmitUrl, string baseDownloadUrl)
            : base(siteName, siteHomeUrl, searchSubmitUrl, baseDownloadUrl)
        {
        }


        /// <summary>
        /// 搜索小说
        /// </summary>
        /// <param name="keyword"></param>
        /// <returns></returns>
        public async Task<List<NovelInfo>> SearchNovel(string keyword)
        {
            List<NovelInfo> novels = new List<NovelInfo>();

            string cacheKey = $"{this.SiteName}_search_{keyword}";
            var cacheValue = MemoryCacheHelper.GetCacheItem<List<NovelInfo>>(cacheKey);
            if (cacheValue == null)
            {
                try
                {
                    string htmlCode = await this.SearchSubmitUrl.WithTimeout(10).PostUrlEncodedAsync(new { searchkey = keyword }).ReceiveString();
                    var doc = ParseHtml.GetDocument(htmlCode);

                    var searchmain = doc.QuerySelector("#searchmain").InnerHtml;

                    string pattern2 = "<div class=\"searchTopic\">.*?\\[<a href=\"(.*?)\" title=\"(.*?)\" target=\"_blank\">.*?/作者：(.*?)</a>\\]</div>";
                    Regex regex2 = new Regex(pattern2);
                    var matchs = regex2.Matches(searchmain);
                    if (matchs.Count <= 0) { return null; }

                    foreach (Match m in matchs)
                    {
                        NovelInfo novel = new NovelInfo();
                        novel.NovelName = m.Groups[2].Value;
                        novel.NovelLink = m.Groups[1].Value;
                        novel.LatestChapter = "";
                        novel.Author = m.Groups[3].Value;
                        novel.LatestChapter = "";

                        novels.Add(novel);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    return null;
                }

                MemoryCacheHelper.SetCacheItem(cacheKey, novels, TimeSpan.FromMinutes(5));
            }
            else
            {
                novels = cacheValue;
            }

            return novels;
        }


        /// <summary>
        /// 获取全部章节信息
        /// </summary>
        /// <param name="novelUrl"></param>
        /// <returns></returns>
        public async Task<List<ChapterInfo>> GetAllChapterInfo(string novelUrl)
        {
            List<ChapterInfo> chapters = new List<ChapterInfo>();
            var novelId = novelUrl.Substring(novelUrl.LastIndexOf("/") + 1);
            var readLink = $"{this.SiteHomeUrl}read/{novelId}";

            string cacheKey = $"{this.SiteName}_{novelUrl}_chapter";
            var cacheValue = MemoryCacheHelper.GetCacheItem<List<ChapterInfo>>(cacheKey);

            if (cacheValue == null)
            {
                string htmlCode = await readLink.GetStringAsync();
                var doc = ParseHtml.GetDocument(htmlCode);

                var aList = doc.QuerySelectorAll("div.read_list a");

                foreach (var a in aList)
                {
                    ChapterInfo chapter = new ChapterInfo();
                    chapter.ChapterTitle = a.Attributes["title"].Value;
                    chapter.ChapterLink = a.Attributes["href"].Value;

                    chapters.Add(chapter);
                }

                MemoryCacheHelper.SetCacheItem(cacheKey, chapters, TimeSpan.FromMinutes(5));
            }
            else
            {
                chapters = cacheValue;
            }

            return chapters;
        }


        /// <summary>
        /// 获取章节内容
        /// </summary>
        /// <param name="chapterUrl"></param>
        /// <returns></returns>
        public async Task<string> GetChapterContent(string chapterUrl)
        {
            string contentStr;

            string cacheKey = $"{this.SiteName}_chapterContent_{chapterUrl}";
            var cacheValue = MemoryCacheHelper.GetCacheItem<string>(cacheKey);

            if (cacheValue == null)
            {
                string htmlCode = await chapterUrl.GetStringAsync();
                var doc = ParseHtml.GetDocument(htmlCode);

                var content = doc.QuerySelector("#view_content_txt");
                content.QuerySelector("div.view_page").Remove();

                //contentStr = content.InnerHtml
                //    .Replace("〖TXT小说下载：www.ibiquta.com〗", "")
                //    .Replace("<div><script>read_bottom_1();</script></div>", "")
                //    .Replace("&nbsp;", "")
                //    .Replace("<br>", "");

                var contentStrSb = new StringBuilder(content.InnerHtml);
                contentStr = contentStrSb
                    .Replace("〖TXT小说下载：www.ibiquta.com〗", "")
                    .Replace("<div><script>read_bottom_1();</script></div>", "")
                    .Replace("&nbsp;", "")
                    .Replace("<br>", "")
                    .ToString();


                MemoryCacheHelper.SetCacheItem<string>(cacheKey, contentStr, TimeSpan.FromMinutes(5));
            }
            else
            {
                contentStr = cacheValue;
            }
            return contentStr;
        }



        /// <summary>
        /// 下载
        /// </summary>
        /// <param name="savePath"></param>
        /// <param name="downloadUrl"></param>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public async Task<string> DownloadNovel(string savePath, string downloadUrl, string fileName)
        {
            try
            {
                string path = await downloadUrl.WithTimeout(10).DownloadFileAsync(savePath, fileName);
                return path;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return null;
            }
        }
    }
}
